package cn.promonkey.api.common.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import cn.promonkey.core.base.Constants;
import cn.promonkey.core.dto.UserDto;
import cn.promonkey.core.response.ResultMsg;
import cn.promonkey.core.toolkit.UserInfoUtils;
import cn.promonkey.core.utils.MD5Utils;
import cn.promonkey.core.utils.RedisUtils;
import cn.promonkey.sso.entity.LoginUser;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import cn.promonkey.api.business.entity.Business;
import cn.promonkey.api.business.service.BusinessService;
import cn.promonkey.api.common.entity.RegisterDto;
import cn.promonkey.api.group.entity.Group;
import cn.promonkey.api.group.service.GroupService;
import cn.promonkey.api.menu.entity.Menu;
import cn.promonkey.api.menu.service.MenuService;
import cn.promonkey.api.permission.entity.Permission;
import cn.promonkey.api.permission.service.PermissionService;
import cn.promonkey.api.relation.entity.Relation;
import cn.promonkey.api.relation.service.RelationService;
import cn.promonkey.api.system.service.SystemService;
import cn.promonkey.api.user.entity.User;
import cn.promonkey.api.user.service.UserService;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Random;

/** @author <no value> */
@Slf4j
@RestController
@RequestMapping("/api/")
public class CommonController {

	final BusinessService businessService;

	final UserService userService;
	
	final SystemService systemService;
	
	final MenuService menuService;
	
	final GroupService groupService;
	
	final PermissionService permissionService;
	
	final RelationService relationService;

	final RedisUtils redisUtils;

	public CommonController(BusinessService businessService, UserService userService, RedisUtils redisUtils,
			SystemService systemService,MenuService menuService,GroupService groupService,
			PermissionService permissionService,RelationService relationService) {
		this.businessService = businessService;
		this.userService = userService;
		this.redisUtils = redisUtils;
		this.systemService = systemService;
		this.menuService = menuService;
		this.groupService = groupService;
		this.permissionService = permissionService;
		this.relationService = relationService;
	}

	@RequestMapping(value = "register", method = RequestMethod.POST)
	public String save(@RequestBody RegisterDto user,
		      HttpServletRequest request) {
		
		LoginUser loginUser = new LoginUser();
		//未登录用户直接注册
		if(user.getUserId() == null) {
			//校验用户信息
			QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
			queryWrapper.eq("user_name", user.getUserName());
			long size = userService.count(queryWrapper);
			if(size>0) {
				return ResultMsg.fail("登录名已存在，请重新输入！已注册用户请登录后新建企业！");
			}
			queryWrapper = new QueryWrapper<User>();
			queryWrapper.or().eq("email", user.getEmail());
			size = userService.count(queryWrapper);
			if(size>0) {
				return ResultMsg.fail("邮箱已存在，请重新输入！已注册用户请登录后新建企业！");
			}
			queryWrapper = new QueryWrapper<User>();
			queryWrapper.or().eq("phone", user.getPhone());
			size = userService.count(queryWrapper);
			if(size>0) {
				return ResultMsg.fail("电话已存在，请重新输入！已注册用户请登录后新建企业！");
			}
			//校验企业信息
			QueryWrapper<Business> businessWrapper = new QueryWrapper<Business>();
			businessWrapper.eq("business_name", user.getBusinessName());
			size = businessService.count(businessWrapper);
			if(size>0) {
				return ResultMsg.fail("企业名称已存在，请确认！");
			}
			//生成一个16位的随机数
			Random random = new Random();
			StringBuilder sBuilder = new StringBuilder(16);
			sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
			int len = sBuilder.length();
			if (len < 16) {
				for (int i = 0; i < 16 - len; i++) {
					sBuilder.append("0");
				}
			}
			// 生成最终的加密盐
			String salt = sBuilder.toString();
			user.setSalt(salt);
			user.setPassword(MD5Utils.md5AndSha(user.getPassword() + user.getSalt()));
			user.setType(0);
			user.setStatus(0);
			user.setDatetime(new Date());
			//保存用户信息
			userService.save(user);
			//走登录请求
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Calendar ca=Calendar.getInstance();
			ca.setTime(new Date());
			String accessToken = MD5Utils.md5AndSha(user.getUserId() + sdf.format(ca.getTime()) + salt);
			ca.add(Calendar.HOUR_OF_DAY, 3);
			String refreshToken = MD5Utils.md5AndSha(user.getUserId() + sdf.format(ca.getTime()) + salt);
			//redis缓存
			redisUtils.hset(Constants.ACCESS_TOKEN_HASH, accessToken, user.getUserId(), 30*24*60*60);
			redisUtils.hset(Constants.REFRESH_TOKEN_HASH, refreshToken, user.getUserId(), 3*30*24*60*60);
			
			//授权token
			loginUser.setAccess_token(accessToken);
			//刷新token
			loginUser.setRefresh_token(refreshToken);
			//到期时间,1小时，刷新token3小时
			loginUser.setExpires_in(60*60);
			loginUser.setToken_type("1");
			loginUser.setUsername(user.getPhone());
			loginUser.setUserName(user.getUserName());
			loginUser.setType(user.getType());
			loginUser.setUserId(user.getUserId());
		}else {
			String accessToken = request.getHeader("Authorization");
	    	Object uid = redisUtils.hget(Constants.ACCESS_TOKEN_HASH, accessToken);
			//Object refreshToken = redisUtils.hget(Constants.REFRESH_TOKEN_HASH, loginUser.getRefresh_token());
			if(uid == null) {
				return ResultMsg.fail(401, "登录超时");
			}
		}
		//插入企业表
		Business business = new Business();
		business.setBusinessName(user.getBusinessName());
		business.setExpirationDate(new Date((new Date()).getTime() + 1000l * 60 * 60 * 24 * 15));
		business.setStatus(0);
		business.setUserId(user.getUserId());
		businessService.save(business);
		//redis缓存
		redisUtils.hset(Constants.BUSINESS_ID, user.getUserId()+"",business.getBusinessId());
		user.setBusinessId(business.getBusinessId());
		//保存用户信息
		userService.updateById(user);
		//生成默认应用
		cn.promonkey.api.system.entity.System system = systemService.getById(1);
		system.setSystemId(null);
		system.setBusinessId(business.getBusinessId());
		system.setUserId(user.getUserId());
		systemService.save(system);
		//生成对应菜单
		QueryWrapper<Menu> menuWrapper = new QueryWrapper<Menu>();
		menuWrapper.eq("system_id", 1);
		List<Menu> menuList = menuService.list(menuWrapper);
		for(Menu m:menuList) {
			m.setMenuId(null);
			m.setBusinessId(business.getBusinessId());
			m.setSystemId(system.getSystemId());
		}
		menuService.saveBatch(menuList);
		//生成默认权限组
		Group group = new Group();
		group.setBusinessId(business.getBusinessId());
		group.setSystemId(system.getSystemId());
		group.setUserId(user.getUserId());
		group.setType(1);
		group.setStatus(1);
		group.setGroupName("默认权限组");
		groupService.save(group);
		//生成授权信息
		List<Permission> permissionList = new ArrayList<>();
		for(Menu m:menuList) {
			Permission p = new Permission();
			p.setBusinessId(business.getBusinessId());
			p.setSystemId(system.getSystemId());
			p.setGroupId(group.getGroupId());
			p.setMenuId(m.getMenuId());
			p.setInterfaceId(0);
			p.setButtonId(0);
			permissionList.add(p);
		}
		permissionService.saveBatch(permissionList);
		//授权给注册用户
		Relation relation = new Relation();
		relation.setBusinessId(business.getBusinessId());
		relation.setSystemId(system.getSystemId());
		relation.setGroupId(group.getGroupId());
		relation.setUserId(user.getUserId());
		relationService.save(relation);
		return ResultMsg.success(loginUser);
	}
	
	@Value("${upload.path}")
    private String uploadPath;
	
	
	@RequestMapping("upload")
	  public String upload(MultipartFile file) throws SocketException, IOException {
		  Date now=new Date();    //创建一个Date对象，获取当前时间
	      //指定格式化格式
	      SimpleDateFormat f=new SimpleDateFormat("yyyyMMddHHmmss");
		  String fileName = f.format(now) + file.getOriginalFilename();//获取文件名
	      if (!file.isEmpty()) {
	          try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(uploadPath + fileName)))) {
	              out.write(file.getBytes());
	              out.flush();
	              System.out.println("文件上传成功，文件名：" + fileName);
	          }catch(Exception e) {
	        	  return ResultMsg.fail(e.getMessage());
	          }
	      }else {
	    	  return ResultMsg.fail("文件不可为空！");
	      }
		  return ResultMsg.success(fileName);
	  }	
	  
	  @RequestMapping(value = "download")
	  public void download(@RequestParam("fileName") String filename) throws IOException {
	      ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
	      HttpServletResponse response = requestAttributes.getResponse();
	      // 设置信息给客户端不解析
	      Optional<MediaType> mediaType = MediaTypeFactory.getMediaType(filename);
	      String type = mediaType.orElse(MediaType.APPLICATION_OCTET_STREAM).toString();
	      
	      
	      //String type = new MimetypesFileTypeMap().getContentType(filename);
	      // 设置contenttype，即告诉客户端所发送的数据属于什么类型
	      response.setHeader("Content-type",type);
			/*
			 * if(filename.endsWith("png")||filename.endsWith("PNG")) {
			 * response.setContentType(MediaType.IMAGE_PNG_VALUE); }else
			 * if(filename.endsWith("jpg")||filename.endsWith("JPG")||filename.endsWith(
			 * "jpeg")||filename.endsWith("JPEG")){
			 * response.setContentType(MediaType.IMAGE_JPEG_VALUE); }else
			 * if(filename.endsWith("gif")||filename.endsWith("GIF")) {
			 * response.setContentType(MediaType.IMAGE_GIF_VALUE); }else {
			 * response.setContentType(MediaType.IMAGE_JPEG_VALUE); }
			 */
	      // 设置编码
	      String hehe = new String(filename.getBytes("utf-8"), "iso-8859-1");
	      // 设置扩展头，当Content-Type 的类型为要下载的类型时 , 这个信息头会告诉浏览器这个文件的名字和类型。
	      response.setHeader("Content-Disposition", "attachment;filename=" + hehe);
	      // 发送给客户端的数据
	      OutputStream outputStream = response.getOutputStream();
	      byte[] buff = new byte[1024];
	      BufferedInputStream bis = null;
	      // 读取filename
	      bis = new BufferedInputStream(new FileInputStream(new File(uploadPath + filename)));
	      int i = bis.read(buff);
	      while (i != -1) {
	          outputStream.write(buff, 0, buff.length);
	          outputStream.flush();
	          i = bis.read(buff);
	      }
	      bis.close();
	      outputStream.close();
	  }

}
